package com.naiterui.ehp.bs.esign.utils;

import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.date.DateUtil;
import com.naiterui.ehp.bp.utils.esign.ESignUtils;
import com.naiterui.ehp.bs.esign.exception.ExceptionCodes;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.UUID;
import javax.imageio.ImageIO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import sun.awt.image.BufferedImageGraphicsConfig;

/**
 * @author guoyongxiang
 * @date 2019-07-17 16:02
 * @since 1.0.0
 */
@Slf4j
public class SealImageUtil {


    /**
     * 生成姓名签章
     *
     * @param text
     * @param path
     * @param color
     *
     * @throws IOException
     */
    public static boolean nameSealGeneration(String text, String path, Color color) throws IOException, FontFormatException {
        int imageWidth = 150;
        int imageHeight = 100;
        double SCALE = 1;
        int w = (int) Math.round(imageWidth * SCALE);
        int h = (int) Math.round(imageHeight * SCALE);
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = image.createGraphics();
        g2d.scale(SCALE, SCALE);

        //image = g2d.getDeviceConfiguration().createCompatibleImage(imageWidth, imageHeight, Transparency.TRANSLUCENT);
        //g2d.dispose();
        //g2d = image.createGraphics();

        if (color == null) {
            color = Color.BLACK;
        }
        g2d.setColor(color);
        g2d.setStroke(new BasicStroke(3.0f));

        // 抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);


        // 设置字体
        Font customFont;
        try (InputStream stream = SealImageUtil.class.getClassLoader().getResourceAsStream("xingkai.ttf")) {
            customFont = Font.createFont(Font.TRUETYPE_FONT, stream).deriveFont(Font.PLAIN, 60);
            GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
            environment.registerFont(customFont);
        }

        // 设置字体
        //Font font = new Font("楷体", Font.BOLD, 17);
        g2d.setFont(customFont);
        FontMetrics fm = g2d.getFontMetrics(customFont);

        int textWidth = fm.stringWidth(text);
        int textHeight = fm.getHeight();
        int textWidthX = (imageWidth - textWidth) / 2;

        g2d.drawString(text, textWidthX, textHeight);

        g2d.dispose();
        File file = new File(path);
        FileUtils.forceMkdirParent(file);
        return ImageIO.write(image, "PNG", file);
    }

    /**
     * 生成红框带标题+姓名签章(无签名日期)
     * --------------------
     * |  海南互联网医院   |
     * |    医生:张三       |
     * --------------------
     *
     * @param title
     * @param text
     * @param path
     *
     * @throws IOException
     */
    public static void graphicsGeneration(String title, String text, String path) throws IOException {
        BufferedImage image = getImage(title, text, false, 17, 30);
        File file = new File(path);
        FileUtils.forceMkdirParent(file);
        ImageIO.write(image, "PNG", file);
    }

    /**
     * 生成红框带标题+姓名签章 + 无签名日期
     * --------------------
     * |    医生:张三      |
     * |  海南互联网医院    |
     * | 2020/04/23 15:25 |
     * --------------------
     *
     * @param title
     * @param text
     *
     * @return 签章base64字符串
     *
     * @throws IOException
     */
    public static String graphicsGenerationBase64(String title, String text) throws IOException {
        BufferedImage image = getImage(title, text, true, 14, 20);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "PNG", outputStream);
        return Base64.encodeBase64String(outputStream.toByteArray());
    }

    private static BufferedImage getImage(String title, String text, boolean dateFlag, int fontSize, int lineSpace) throws IOException {
        // 实际数据行数+标题+备注
        int imageWidth = 235;
        int imageHeight = 95;
        double SCALE = 1;
        int w = (int) Math.round(imageWidth * SCALE);
        int h = (int) Math.round(imageHeight * SCALE);
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = image.createGraphics();
        g2d.scale(SCALE, SCALE);

        // ---------- 增加下面的代码使得背景透明 -----------------
        //image = g2d.getDeviceConfiguration().createCompatibleImage(imageWidth, imageHeight, Transparency.TRANSLUCENT);
        //g2d.dispose();
        //g2d = image.createGraphics();
        // ---------- 背景透明代码结束 -----------------
        Color red = new Color(237, 123, 117);
        g2d.setColor(red);
        g2d.setStroke(new BasicStroke(3.0f));

        g2d.drawRect(5, 5, imageWidth - 5 * 2, imageHeight - 5 * 2);

        // 抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);


        // 设置字体
        Font font = new Font("楷体\\-简", Font.BOLD, fontSize);
        g2d.setFont(font);
        FontMetrics fm = g2d.getFontMetrics(font);

        int textY = 33;
        int textWidth = fm.stringWidth(text);
        int textWidthX = (imageWidth - textWidth) / 2;
        g2d.drawString(text, textWidthX, textY);

        int titleY = textY + lineSpace;
        int titleWidth = fm.stringWidth(title);
        int widthX = (imageWidth - titleWidth) / 2;
        g2d.drawString(title, widthX, titleY);

        if (dateFlag) {
            int dateY = titleY + lineSpace;
            String dateStr = DateUtil.formatDate(new Date(), DateUtil.DATE_FORMAT_BY_DIAGONAL_MIN);
            int dateWidth = fm.stringWidth(dateStr);
            int dateWidthX = (imageWidth - dateWidth) / 2;
            g2d.drawString(dateStr, dateWidthX, dateY);
        }

        g2d.dispose();
        return image;
    }

    /**
     * 签名文件填充处理：根据原签名文件宽度生成新的正方形图片，并将原签名图片放置在正方形底部
     *
     * @param filePath
     * @throws IOException
     */
    public static String modifySealImage(String filePath) throws BusinessException {
        try {
            File file = new File(filePath);
            BufferedImage bufferedImage = ImageIO.read(file);

            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            BufferedImage bufferedImage2 = new BufferedImage(width, width, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = bufferedImage2.createGraphics();

            //设置透明背景色
            BufferedImageGraphicsConfig config = BufferedImageGraphicsConfig.getConfig(bufferedImage2);
            bufferedImage2 = config.createCompatibleImage(width, width, Transparency.TRANSLUCENT);
            g2d = bufferedImage2.createGraphics();


            g2d.drawImage(bufferedImage, 0, width - height, width, height, null);
            g2d.dispose();

            //生成新的签名文件
            String newPath = file.getParent() + "/" + UUID.randomUUID().toString() + ".png";
            ImageIO.write(bufferedImage2, "png", new File(newPath));
            return newPath;
        } catch (IOException e) {
            log.error("签名文件填充处理失败 filePath:{}", filePath, e);
            throw new BusinessException(ExceptionCodes.ESIGN_SIGN_SEALDATA_ERR, "签名图片填充处理失败");
        }
    }

    /**
     * 裁剪图片
     * @param filePath
     * @return
     * @throws BusinessException
     */
    public static String cutSealImage(String filePath) throws BusinessException{
        File file = new File(filePath);
        try {
            BufferedImage bufferedImage = ImageIO.read(file);
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            //图片裁剪
            int x = bufferedImage.getMinX();
            int y = bufferedImage.getMinY();
            y += height / 5;
            height = height / 2;
            bufferedImage = bufferedImage.getSubimage(x, y, width, height);
            String newPath = file.getParent() + "/" + UUID.randomUUID().toString() + ".png";
            ImageIO.write(bufferedImage, "png", new File(newPath));
            return newPath;
        } catch (IOException e) {
            log.error("图片裁剪失败 filePath:{}", filePath, e);
            throw new BusinessException(ExceptionCodes.ESIGN_SIGN_SEALDATA_ERR, "签名图片裁剪处理失败");
        }

    }


    /**
     * 根据签名配置设置签章图片
     * @param sealImage
     * @return
     * @throws BusinessException
     */
    public static String setSealImage(String sealImage) throws BusinessException {
        String newPath = Constants.BASE_PATH + sealImage;
        log.info("手写签章图片处理: sealImage={}, signWay={}", sealImage, ESignUtils.getSealType());
        //当签名方式为手写时，进行签章图片处理
        if (StringUtils.isNotBlank(sealImage) && ESignUtils.isHandWriting()) {
            //签名图片填充处理
            newPath = SealImageUtil.modifySealImage(newPath);
        }
        newPath = newPath.replace(Constants.BASE_PATH, "");
        return newPath;

    }


}
